home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Tools 2
/
Amiga Tools 2.iso
/
tools
/
jade
/
lisp
/
compile.jl
< prev
next >
Wrap
Lisp/Scheme
|
1995-03-09
|
9KB
|
255 lines
;;;; compile.jl -- Running compilation processes
;;; Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
;;; This file is part of Jade.
;;; Jade is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 2, or (at your option)
;;; any later version.
;;; Jade is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;; You should have received a copy of the GNU General Public License
;;; along with Jade; see the file COPYING. If not, write to
;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
(provide 'compile)
(setq gcc-error-regexp "^(.*):([0-9]+):(.+)"
gcc-file-expand "\\1"
gcc-line-expand "\\2"
gcc-error-expand "\\3")
(defvar compile-error-regexp gcc-error-regexp
"String used to match error messages in compilation output.")
(defvar compile-file-expand gcc-file-expand
"Expansion template for the name of the file in an error matched by
`compile-error-regexp'.")
(defvar compile-line-expand gcc-line-expand
"Expansion template for the line number of an error matched by
`compile-error-regexp'.")
(defvar compile-error-expand gcc-error-expand
"Expansion template for the error description in an error matched by
`compile-error-regexp'.")
(defvar compile-keymap (make-keylist))
(unless (boundp 'compile-buffer)
(bind-keys compile-keymap
"Ctrl-c" 'kill-compilation
"Ctrl-z" 'stop-compilation
"Ctrl-f" 'continue-compilation
"r" '(start-compile-command compile-default-cmd compile-type-str)
"Ctrl-r" 'compile))
(defvar compile-buffer nil)
(defvar compile-proc nil)
(defvar compile-errors nil "List of (ERROR-POS-MARK . ERROR-DESC-LINE)")
(defvar compile-error-pos nil)
(defvar compile-type-str nil)
(defvar compile-error-parsed-errors-p nil)
(defvar compile-errors-exist-p nil)
(defvar compile-default-cmd "make"
"Default command which `(compile)' executes, the value of the last
command executed by `(compile)'.")
(defvar compile-command nil
"Buffer-local symbol which contains the command to compile this buffer. If
nil or unbound use `compile-default-cmd'.")
(make-variable-buffer-local 'compile-command)
(defvar compile-shell (unless (getenv "SHELL") "/bin/sh")
"The filename of the shell to use to run the compilation in.")
(defun compile-init ()
(if compile-buffer
(clear-buffer compile-buffer)
(setq compile-buffer (make-buffer "*compilation*"))
(with-buffer compile-buffer
(setq ctrl-c-keymap compile-keymap))
(set-buffer-special compile-buffer t))
(when compile-buffer
(add-buffer compile-buffer)
(set-buffer-file-name compile-buffer (file-name-directory (buffer-file-name)))
(setq compile-errors nil
compile-parsed-errors-p nil
compile-errors-exists-p nil
compile-error-pos (buffer-start))
t))
(defun compile-callback ()
(when compile-proc
(cond
((process-stopped-p compile-proc)
(write (cons compile-buffer t) "Compilation suspended..."))
((process-running-p compile-proc)
(write (cons compile-buffer t) "restarted\n"))
(t
(beep)
(if (process-exit-value compile-proc)
(format (cons compile-buffer t) "\n%s%d\n"
"Compilation exited with value "
(process-exit-value compile-proc))
(format (cons compile-buffer t) "\n%s%x\n"
"Compilation exited abnormally: status 0x"
(process-exit-status compile-proc)))
(setq compile-proc nil)))))
;;;###autoload
(defun start-compile-command (command type-str)
"<UNIX-ONLY>
Executes SHELL-COMMAND asynchronously in the directory containing the file
being edited in the current buffer. Output from the process is sent to the
`*compilation*' buffer. TYPE-STR is a string describing the type of messages
the command may output (i.e. `errors' for a compilation)."
(if compile-proc
(error "Compilation process already running")
(save-some-buffers)
(compile-init)
(goto-buffer compile-buffer)
(setq compile-proc (make-process (cons compile-buffer t)
'compile-callback
(file-name-directory (buffer-file-name))))
(let
((shell-cmd (concat command ?\n)))
(write compile-buffer shell-cmd)
(when (start-process compile-proc compile-shell "-c" shell-cmd)
(setq compile-type-str type-str)
compile-proc))))
(defun kill-compilation ()
(interactive)
(when compile-proc
(interrupt-process compile-proc t)))
(defun stop-compilation ()
(interactive)
(when (process-running-p compile-proc)
(stop-process compile-proc t)))
(defun continue-compilation ()
(interactive)
(when (process-stopped-p compile-proc)
(continue-process compile-proc t)))
;;;###autoload
(defun compile (&optional shell-command)
"<UNIX-ONLY>
Runs the SHELL-COMMAND in the `*compilation*' buffer. If SHELL-COMMAND isn't
given you will be prompted for a command."
(interactive)
(unless shell-command
(setq shell-command (or compile-command
(setq
compile-default-cmd
(prompt "Compile command: "
compile-default-cmd)))))
(when shell-command
(start-compile-command shell-command "errors")))
(defun compile-parse-errors ()
;; This can be called while the process is still running, one problem though,
;; if the compiled file is modified and then a new error is found the line
;; numbers won't coincide like they normally would.
(unless compile-parsed-errors-p
(with-buffer compile-buffer
(let*
(error-file
error-line
last-e-line
last-e-file
new-errors)
(while (setq compile-error-pos (find-next-regexp compile-error-regexp
compile-error-pos))
(setq error-line (1- (read-from-string (regexp-expand-line
compile-error-regexp
compile-line-expand
compile-error-pos))))
(when (or (not last-e-line) (/= error-line last-e-line))
(setq last-e-line error-line
error-file (file-name-concat (buffer-file-name)
(regexp-expand-line
compile-error-regexp
compile-file-expand
compile-error-pos)))
(if (equal last-e-file error-file)
(setq error-file last-e-file)
(setq last-e-file error-file))
(setq new-errors (cons (cons (make-mark (pos 0 error-line)
error-file)
(pos-line compile-error-pos))
new-errors)))
(setq compile-error-pos (match-end)))
(when new-errors
(setq compile-errors (nconc compile-errors (nreverse new-errors))
compile-errors-exist-p t))))
(unless compile-proc
(setq compile-parsed-errors-p t)))
t)
;;;###autoload
(defun next-error ()
"Moves the cursor to the file and line of the next error displayed in the
`*compilation*' buffer."
(interactive)
(compile-parse-errors)
(let*
((err (car compile-errors)))
(setq compile-errors (cdr compile-errors))
(cond
((not err)
(message (concat "No " (if compile-errors-exist-p "more ")
compile-type-str (if compile-proc " yet")))
(beep)
nil)
(t
(goto-mark (car err))
(when (cdr err)
(message (regexp-expand-line compile-error-regexp compile-error-expand
(pos 0 (cdr err)) compile-buffer)))
t))))
;;;###autoload
(defun grep (args-string)
"<UNIX-ONLY>
Runs the `grep' program with ARGS-STRING (or the result of a prompt) and
sends its output to the `*compilation*' buffer. The `grep' process may still
be executing when this function returns."
(interactive "sGrep with args:")
(when args-string
(start-compile-command (concat "grep -n "
args-string
" /dev/null /dev/null")
"grep-hits")))
(defvar grep-buffer-regexp nil
"Regular-expression which `grep-buffer' scans for")
;;;###autoload
(defun grep-buffer (&optional regexp)
"Scans the current buffer for all matches of REGEXP (or the contents of
variable `grep-buffer-regexp'). All hits are displayed in the `*compilation*'
buffer in a form that `goto-next-error' understands."
(interactive)
(when regexp
(setq grep-buffer-regexp regexp))
(when (and grep-buffer-regexp (compile-init))
(let*
((scanpos (buffer-start))
(number 0)
(stream (cons compile-buffer t)))
(write stream ?\n)
(while (setq scanpos (find-next-regexp grep-buffer-regexp scanpos))
(format stream "%s:%d:%s\n" (buffer-file-name) (pos-line scanpos)
(copy-area (line-start scanpos) (line-end scanpos)))
(setq number (+ number 1)
scanpos (line-end scanpos)))
(goto-buffer compile-buffer)
(goto-buffer-start)
number)))